﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;

namespace CMS.Util
{
    /// <summary>
    /// 窗口/控件小工具
    /// </summary>
    public static class FormUtils
    {
        /// <summary>
        /// 表示一个需要操作UI的代码,但是又有可能多线程调用
        /// </summary>
        public delegate void InvokeHandler();

        /// <summary>
        /// 表示一个需要操作UI并返回数据的代码
        /// </summary>
        public delegate T InvokeHandlerEx<T>();

        /// <summary>
        /// 安全执行UI相关的操作,但没有返回值
        /// </summary>
        /// <param name="control"></param>
        /// <param name="handler"></param>
        public static void Invoke(this Control control, InvokeHandler handler)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(handler);
            }
            else
            {
                handler();
            }
        }

        /// <summary>
        /// 安全执行UI相关的操作,可以有返回值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <param name="handler"></param>
        /// <returns></returns>
        public static T Invoke<T>(this Control control, InvokeHandlerEx<T> handler)
        {
            if (control.InvokeRequired)
            {
                return (T)control.Invoke(handler);
            }
            else
            {
                return handler();
            }
        }

        /// <summary>
        /// 保留所选元素进行更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="comboBox"></param>
        /// <param name="syncField"></param>
        /// <param name="data"></param>
        public static void SyncComboBoxData<T>(this ComboBox comboBox, string syncField, T[] data)
        {
            if (comboBox.SelectedIndex == -1)
            {
                comboBox.DataSource = new BindingList<T>(data);
            }
            else
            {
                if (syncField != null)
                {
                    MethodInfo method = typeof(T).GetProperty(syncField).GetMethod;
                    object[] empty = new object[0];
                    T oldT = (T)comboBox.SelectedItem;
                    object target = method.Invoke(oldT, empty);
                    List<T> list = new List<T>(data);
                    T newT = list.Find(t => Equals(method.Invoke(t, empty), target));
                    comboBox.DataSource = list;
                    comboBox.SelectedItem = newT;
                }
                else
                {
                    object oldT = comboBox.SelectedItem;
                    List<T> list = new List<T>(data);
                    comboBox.DataSource = list;
                    comboBox.SelectedItem = oldT;
                }
            }
        }
    }
}
